#pragma once

#include <iostream>
#include <memory>
#include <string>
#include <jsoncpp/json/json.h>
const std::string ProtSep = " ";
const std::string LineBreakSep = "\n";

//序列加上len头
std::string EnCode(const std::string& message)  //通过返回值拿
{
    std::string len = std::to_string(message.size());
    std::string package = len + LineBreakSep + message + LineBreakSep;
    return package;
}
//解开序列
//"len\nx op y\n""len\n
bool DeCode(std::string& package, std::string* message) //通过参数拿出来
{
    //len不全，退出
    int pos = package.find(LineBreakSep);
    if(pos == std::string::npos) return false;
    // std::cout << pos << std::endl; //DEBUG
    std::string len = package.substr(0, pos);
    // std::cout << len << std::endl; //DEBUG
    // int sum_len = len.size() + sizeof(LineBreakSep) * 2 + stoi(len); //不是sizeof
    int sum_len = len.size() + LineBreakSep.size() * 2 + stoi(len);
    // std::cout << sum_len << std::endl; //DEBUG  //找到了
    if(sum_len < package.size()) return false;

    // *message = package.substr(len.size() + sizeof(LineBreakSep), stoi(len));  //这里也是
    *message = package.substr(len.size() + LineBreakSep.size(), stoi(len));
    // std::cout << *message << std::endl;
    package.erase(0, sum_len);
    return true;
}
class Request
{
public:
    Request() {}
    Request(int x, int y, char ch)
        : _data_x(x), _data_y(y), _oper(ch)
    {
    }

    void Debug()
    {
        std::cout << "_data_x: " << _data_x << std::endl;
        std::cout << "_data_y: " << _data_y << std::endl;
        std::cout << "_oper: " << _oper << std::endl;
    }
    int GetX() { return _data_x; }
    int GetY() { return _data_y; }
    char getOper() { return _oper; }

    //结构体序列化
    bool Serialize(std::string* out)
    {
#ifdef SelfDefine
        *out = std::to_string(_data_x) + ProtSep + _oper + ProtSep + std::to_string(_data_y);
        return true;
#else
        Json::Value root;
        root["_data_x"] = _data_x;
        root["_data_y"] = _data_y;
        root["_oper"] = _oper;

        Json::FastWriter writer;
        *out = writer.write(root);
        return true;
#endif
    }
    //字符串反序列化，设置进结构体
    bool DeSerialize(std::string& in)
    {
#ifdef SelfDefine
        int left_pos = in.find(ProtSep);
        if(left_pos == std::string::npos) return false;
        int right_pos = in.find(ProtSep, left_pos + ProtSep.size());
        if(right_pos == std::string::npos) return false;

        _data_x = std::stoi(in.substr(0, left_pos));
        _data_y = std::stoi(in.substr(right_pos + ProtSep.size()));
        std::string oper = in.substr(left_pos + ProtSep.size(), right_pos - (left_pos + ProtSep.size()));
        if(oper.size() != 1) return false;
        _oper = oper[0];
        return true;
#else
        Json::Value root;
        Json::Reader reader;
        bool flag = reader.parse(in, root);
        if(flag)
        {
            _data_x = root["_data_x"].asInt();
            _data_y = root["_data_y"].asInt();
            _oper = root["_oper"].asInt();
        }
        return flag;
#endif
    }
private:
    int _data_x;
    int _data_y;
    char _oper;
};

class Response
{
public:
    Response():_result(0), _code(true) {}
    Response(int result, int code)
        : _result(result), _code(code)
    {
    }
    void SetResult(int result) { _result = result; }
    void SetCode(int code) { _code = code; }
    int GetResult() { return _result; }
    int GetCode() { return _code; }

    //结构体序列化
    bool Serialize(std::string* out)
    {
#ifdef SelfDefine
        *out = std::to_string(_result) + ProtSep + std::to_string(_code);
        return true;
#else
        Json::Value root;
        root["_result"] = _result;
        root["_code"] = _code;
        Json::FastWriter writer;
        *out = writer.write(root);
        return true;
#endif
    }

    //字符串反序列化，设置进结构体
    bool DeSerialize(std::string& in)
    {
#ifdef SelfDefine
        int pos = in.find(ProtSep);
        if(pos == std::string::npos) return false;

        _result = std::stoi(in.substr(0, pos));
        _code = std::stoi(in.substr(pos + ProtSep.size()));
        return true;
#else
        Json::Value root;
        Json::Reader reader;
        bool flag = reader.parse(in, root);
        if(flag)
        {
            _result = root["_result"].asInt();
            _code = root["_oper"].asInt();
        }
        return flag;
#endif
    }
private:
    int _result;
    int _code;
};

class Factory
{
public:
    std::shared_ptr<Request> BuildRequest()
    {
        // std::shared_ptr<Request> req = std::make_shared<Request>();
        // return req;
        return std::make_shared<Request>();
    }
    std::shared_ptr<Request> BuildRequest(int x, int y, char op)
    {
        return std::make_shared<Request>(x, y, op);
    }
    std::shared_ptr<Response> BuildResponse()
    {
        return std::make_shared<Response>();
    }
    std::shared_ptr<Response> BuildResponse(int result, int code)
    {
        return std::make_shared<Response>(result, code);
    }
};